package com.yumeng.framework.auth.security;

import com.yumeng.common.utils.SpringUtils;
import com.yumeng.common.auth.AbsAuthHelper;
import com.yumeng.common.auth.CommAuthDetails;
import com.yumeng.framework.auth.bean.authinfo.AnonAuthInfo;
import com.yumeng.common.auth.BaseAuthInfo;
import com.yumeng.framework.auth.exception.SecurityAuthException;
import com.yumeng.framework.auth.security.authentication.custom.CustomWebAuthenticationDetails;
import com.yumeng.framework.auth.security.bean.MyUserDetails;
import com.yumeng.framework.auth.security.custom.AuthInfoResolver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authorization.AuthorizationDeniedException;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 *
 * @author wxd
 * @date 2025/9/22 13:31
 */
@Slf4j
@Component
public class SecurityAuthHelper extends AbsAuthHelper {

    private static AuthInfoResolver resolver = null;

    @Autowired(required = false)
    public void setAuthInfoResolver(AuthInfoResolver resolver) {
        SecurityAuthHelper.resolver = resolver;
    }

    @Override
    protected BaseAuthInfo doGetCurrAuthInfo(boolean strict) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        BaseAuthInfo authInfo = getCurrAuthInfo(authentication);
        if (authInfo != null){
            return authInfo;
        }
        if (strict){
            throw new SecurityAuthException("当前认证信息未知");
        }else{
            return AnonAuthInfo.getSingleInstance();
        }
    }

    @Override
    protected void printAuthFrameInfo(ConfigurableApplicationContext context) {
        if (!SpringUtils.containsBean(AuthenticationConfiguration.class)){
            log.info("Spring-Security:未注入AuthenticationManager");
            return;
        }
        AuthenticationConfiguration authenticationConfiguration = context.getBean(AuthenticationConfiguration.class);

        AuthenticationManager authenticationManager = null;
        try {
            authenticationManager = authenticationConfiguration.getAuthenticationManager();
        } catch (Exception e) {
            throw new SecurityAuthException("获取AuthenticationManager对象失败：%s", e.getMessage());
        }
        if (authenticationManager == null){
            throw new SecurityAuthException("未获取到AuthenticationManager对象");
        }
        if (authenticationManager instanceof ProviderManager providerManager){
            List<AuthenticationProvider> providers = providerManager.getProviders();
            log.info("Spring-Security:全局AuthenticationManager:providers数量：{}", providers.size());
            int index = 0;
            for (AuthenticationProvider provider : providers){
                log.info("Spring-Security:全局AuthenticationManager:providers[{}]：{}", index, provider.getClass().getName());
                index++;
            }
        }else {
            log.info("Spring-Security:全局AuthenticationManager【打印日志未实现】：{}", authenticationManager.getClass().getName());
        }
    }

    @Override
    protected boolean needThrowException(Exception ex) {
        if (ex instanceof AuthorizationDeniedException){
            return true;
        }
        return false;
    }

    /**
     * 获取当前认证信息
     *
     * @return
     */
    public static BaseAuthInfo getCurrAuthInfo(Authentication authentication){
        if (authentication == null || authentication.getPrincipal() == null) {
            throw new SecurityAuthException("current authentication is null");
        }
        if (!authentication.isAuthenticated()){
            throw new SecurityAuthException("当前用户未认证");
        }
        BaseAuthInfo authInfo = null;
        if (authentication.getPrincipal() instanceof MyUserDetails userDetails) {
            authInfo = userDetails.getAuthInfo();
        }else if (authentication instanceof AnonymousAuthenticationToken anonUser) {
            authInfo = AnonAuthInfo.getSingleInstance();
        }
        if (authInfo == null && resolver != null) {
            authInfo = resolver.resolve(authentication);
        }
        if (authInfo == null) {
            throw new SecurityAuthException("未识别当前用户类型");
        }

        CommAuthDetails details = new CommAuthDetails();
        if (authentication.getDetails() instanceof CustomWebAuthenticationDetails authDetails){
            details.setSessionId(authDetails.getSessionId());
            details.setRemoteAddress(authDetails.getRemoteAddress());
            details.setAuthClientType(authDetails.getAuthClientType());
        } else if (authentication.getDetails() instanceof WebAuthenticationDetails authDetails) {
            details.setSessionId(authDetails.getSessionId());
            details.setRemoteAddress(authDetails.getRemoteAddress());
        }
        authInfo.setDetails(details);
        return authInfo;
    }

}
